package com.yunchang.springboot.scheduled.mwsfinance;

import com.yunchang.springboot.base.BaseService;
import com.yunchang.springboot.mapper.caravan.CaravanMskuDataMapper;
import com.yunchang.springboot.mapper.caravan.CaravanStorageLogDataMapper;
import com.yunchang.springboot.mapper.finance.FinanceCaravanDebitCreditRelationMapper;
import com.yunchang.springboot.mapper.mwsfinance.FInventoryDailyMapper;
import com.yunchang.springboot.mapper.mwsfinance.FReceiveMapper;
import com.yunchang.springboot.mapper.mwsreport.MwsDailyInventoryHistoryMapper;
import com.yunchang.springboot.mapper.mwsreport.MwsReceiveInventoryMapper;
import com.yunchang.springboot.mapper.mwsutils.FOverseasWarehouseQuantityMapper;
import com.yunchang.springboot.models.mwsfinance.FReceive;
import com.yunchang.springboot.models.mwsreportbean.MwsReceiveInventory;
import com.yunchang.springboot.utils.DateUtil;
import com.yunchang.springboot.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * 已接收库存
 */
@Component
@Configuration
@Service
@Slf4j
@EnableScheduling
public class FReceiveScheduled extends BaseService {

    private static List<String> EUROPE_COUNTRY_NAME = Arrays.asList("DE", "UK", "FR", "IT", "ES");

    static final String EU = "EU";

    private static final String DEBIT_SUBJECT_ID_PLUS = "140603";

    private static final String DEBIT_SUBJECT_ID_MINUS = "140205";

    private static final String CREDIT_SUBJECT_ID_PLUS = "140205";

    private static final String CREDIT_SUBJECT_ID_MINUS = "140603";

    static final String US = "US";

    static final String CA = "CA";

    static final String MX = "MX";

    static final String JP = "JP";

    static Integer LIMIT_VALUE = 10000;

    static String DOCUMENTS_ID = "JSRKD";

    final
    FPaymentRefundScheduled fPaymentRefundScheduled;

    public FReceiveScheduled(FPaymentRefundScheduled fPaymentRefundScheduled) {
        this.fPaymentRefundScheduled = fPaymentRefundScheduled;
    }

    /**
     * 出入库明细
     */
    @Autowired
    FInventoryDetailsScheduled fInventoryDetailsScheduled;

    /**
     * 已接收库存原始数据
     */
    private MwsReceiveInventoryMapper mwsReceiveInventoryMapper;

    @Autowired
    public void setMwsReceiveInventoryMapper(MwsReceiveInventoryMapper mwsReceiveInventoryMapper) {
        this.mwsReceiveInventoryMapper = mwsReceiveInventoryMapper;
    }

    /**
     * 每日库存记录原始数据
     */
    private MwsDailyInventoryHistoryMapper mwsDailyInventoryHistoryMapper;

    @Autowired
    public void setMwsDailyInventoryHistoryMapper(MwsDailyInventoryHistoryMapper mwsDailyInventoryHistoryMapper) {
        this.mwsDailyInventoryHistoryMapper = mwsDailyInventoryHistoryMapper;
    }

    /**
     * 获取stock_sku
     */
    private CaravanMskuDataMapper caravanMskuDataMapper;

    @Autowired
    public void setCaravanMskuDataMapper(CaravanMskuDataMapper caravanMskuDataMapper) {
        this.caravanMskuDataMapper = caravanMskuDataMapper;
    }

    /**
     * 获取costUnit
     */
    private FinanceCaravanDebitCreditRelationMapper financeCaravanDebitCreditRelationMapper;

    @Autowired
    public void setFinanceCaravanDebitCreditRelationMapper(FinanceCaravanDebitCreditRelationMapper financeCaravanDebitCreditRelationMapper) {
        this.financeCaravanDebitCreditRelationMapper = financeCaravanDebitCreditRelationMapper;
    }

    /**
     * 获取 costUnit
     */
    private FOverseasWarehouseQuantityMapper fOverseasWarehouseQuantityMapper;

    @Autowired
    public void setFOverseasWarehouseQuantityMapper(FOverseasWarehouseQuantityMapper fOverseasWarehouseQuantityMapper) {
        this.fOverseasWarehouseQuantityMapper = fOverseasWarehouseQuantityMapper;
    }

    /**
     * 库存数据
     */
    private FInventoryDailyMapper fInventoryDailyMapper;

    @Autowired
    public void setFInventoryDailyMapper(FInventoryDailyMapper fInventoryDailyMapper) {
        this.fInventoryDailyMapper = fInventoryDailyMapper;
    }

    /**
     * 获取stockSku
     */
    private CaravanStorageLogDataMapper caravanStorageLogDataMapper;

    @Autowired
    public void setCaravanStorageLogDataMapper(CaravanStorageLogDataMapper caravanStorageLogDataMapper) {
        this.caravanStorageLogDataMapper = caravanStorageLogDataMapper;
    }

    /**
     * 已接收库存财务数据
     */
    private FReceiveMapper fReceiveMapper;

    @Autowired
    public void setFReceiveMapper(FReceiveMapper fReceiveMapper) {
        this.fReceiveMapper = fReceiveMapper;
    }


    public void getFReceive(String date) throws ParseException {
        List<MwsReceiveInventory> mwsReceiveInventoryList = mwsReceiveInventoryMapper.selectByFinanceStatus(1, null, date);
        Integer mwsReceiveInventoryListSize = mwsReceiveInventoryList.size();
        int forNum = 1;
        if (mwsReceiveInventoryListSize > LIMIT_VALUE) {
            forNum += mwsReceiveInventoryListSize / LIMIT_VALUE;
            for (; forNum > 0; forNum--) {
                log.info("已接收库存生成财务数据剩余次数：" + forNum);
                mwsReceiveInventoryList = mwsReceiveInventoryMapper.selectByFinanceStatus(1, LIMIT_VALUE, date);
                mwsReceiveInventoryDispose(mwsReceiveInventoryList);
            }
        } else {
            mwsReceiveInventoryDispose(mwsReceiveInventoryList);
        }
    }

    public void mwsReceiveInventoryDispose(List<MwsReceiveInventory> mwsReceiveInventoryList) throws ParseException {
        if (null != mwsReceiveInventoryList && !mwsReceiveInventoryList.isEmpty()) {
            List<Object> fReceiveList = new ArrayList<>(mwsReceiveInventoryList.size());
            for (MwsReceiveInventory mwsReceiveInventory : mwsReceiveInventoryList) {
                FReceive fReceive = new FReceive();
                fReceive.setIsManualAdjustment(1);
                fReceive.setApprovalStatus(1);
                fReceive.setStockSkuStatus(1);
                fReceive.setCountryStatus(1);
                fReceive.setIsInventoryDetails(1);
                fReceive.setDocumentsId(DOCUMENTS_ID + UUIDUtil.getUUID());
                String sellerId = mwsReceiveInventory.getSellerId();
                fReceive.setSellerId(sellerId);
                String fnSku = mwsReceiveInventory.getFnsku();
                fReceive.setFnsku(fnSku);
                String sku = mwsReceiveInventory.getSku();
                fReceive.setSku(sku);
                String country;
                if (getCountry(mwsReceiveInventory.getArea(), mwsReceiveInventory.getFulfillmentCenterId(), fnSku).equals("area")) {
                    fReceive.setCountryStatus(2);
                    country = mwsReceiveInventory.getArea();
                    fReceive.setCountry(mwsReceiveInventory.getArea());
                } else {
                    country = getCountry(mwsReceiveInventory.getArea(), mwsReceiveInventory.getFulfillmentCenterId(), fnSku);
                    fReceive.setCountry(getCountry(mwsReceiveInventory.getArea(), mwsReceiveInventory.getFulfillmentCenterId(), fnSku));
                }
                String date = mwsReceiveInventory.getReceivedDate();
                fReceive.setDate(date);
                String shipmentId = mwsReceiveInventory.getFbaShipmentId();
                fReceive.setShipmentId(shipmentId);
                String fbaShipmentId = mwsReceiveInventory.getFbaShipmentId();
                String stockSku = null;
                Map<String, String> stockSkuMap = getStockSku(sku, country, sellerId, fbaShipmentId);
                if (null != stockSkuMap && !stockSkuMap.isEmpty()) {
                    if (stockSkuMap.containsKey("stockSku4")) {
                        stockSku = stockSkuMap.get("stockSku4");
                        fReceive.setStockSkuStatus(4);
                    }
                    if (stockSkuMap.containsKey("stockSku3")) {
                        stockSku = stockSkuMap.get("stockSku3");
                        fReceive.setStockSkuStatus(3);
                    }
                    if (stockSkuMap.containsKey("stockSku2")) {
                        stockSku = stockSkuMap.get("stockSku2");
                        fReceive.setStockSkuStatus(2);
                    }
                    if (stockSkuMap.containsKey("stockSku")) {
                        stockSku = stockSkuMap.get("stockSku");
                    }
                }
                fReceive.setStockSku(stockSku);
                Integer originalQuantity = mwsReceiveInventory.getQuantity();
                fReceive.setOriginalQuantity(originalQuantity);
                Integer quantity = Math.abs(originalQuantity);
                fReceive.setQuantity(quantity);
                Map<String, Double> costUnitMap = getCostUnit(sellerId, fReceive.getCountry(), sku, stockSku, shipmentId);
                if (null != costUnitMap && !costUnitMap.isEmpty()) {
                    if (costUnitMap.containsKey("costUnit")) {
                        fReceive.setCostUnit(costUnitMap.get("costUnit"));
                    } else if (costUnitMap.containsKey("costUnit3")) {
                        fReceive.setIsManualAdjustment(3);
                        fReceive.setCostUnit(costUnitMap.get("costUnit3"));
                    } else if (costUnitMap.containsKey("costUnit4")){
                        fReceive.setIsManualAdjustment(4);
                        fReceive.setCostUnit(costUnitMap.get("costUnit4"));
                    }else if (costUnitMap.containsKey("costUnit5")){
                        fReceive.setIsManualAdjustment(5);
                        fReceive.setCostUnit(costUnitMap.get("costUnit5"));
                    }else if (costUnitMap.containsKey("costUnit6")){
                        fReceive.setIsManualAdjustment(6);
                        fReceive.setCostUnit(costUnitMap.get("costUnit6"));
                    }else if (costUnitMap.containsKey("costUnit7")){
                        fReceive.setIsManualAdjustment(7);
                        fReceive.setCostUnit(costUnitMap.get("costUnit7"));
                    }
                    fReceive.setAmount(quantity * fReceive.getCostUnit());
                }
                fReceive.setCurrency("RMB");
                if (originalQuantity > 0) {
                    fReceive.setDebitSubjectId(DEBIT_SUBJECT_ID_PLUS);
                    fReceive.setCreditSubjectId(CREDIT_SUBJECT_ID_PLUS);
                } else {
                    fReceive.setDebitSubjectId(DEBIT_SUBJECT_ID_MINUS);
                    fReceive.setCreditSubjectId(CREDIT_SUBJECT_ID_MINUS);
                }
                fReceive.setCreateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fReceive.setUpdateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                mwsReceiveInventory.setFinanceStatus(2);
                fReceiveList.add(fReceive);
            }
            try {
                baseInsertList(fReceiveList);
                mwsReceiveInventoryMapper.updateFinanceStatusByMwsReceiveInventoryList(mwsReceiveInventoryList);
                log.info("已接收库存的财务数据已生成");
            } catch (Exception e) {
                log.error("插入数据是出现错误，已接收库存" + e);
                throw new RuntimeException("插入数据是出现错误，已接收库存");
            }
        } else {
            log.info("未查询到对应的已接收库存数据列表，时间为" + DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
        }
    }

    /**
     * 根据区域和fulfillmentCenterId获取国家名称
     *
     * @param area
     * @param fulfillmentCenterId
     * @return
     */
    public String getCountry(String area, String fulfillmentCenterId, String fnSku) {
        String country = null;
        if (area.equals(JP)) {
            return JP;
        }
        if (EUROPE_COUNTRY_NAME.contains(area)) {
            return "EU";
        }
        if (!StringUtils.isEmpty(fulfillmentCenterId)) {
            country = mwsDailyInventoryHistoryMapper.getCountryByFulfillmentCenterId(fulfillmentCenterId);
        }
        if (StringUtils.isEmpty(country) && !StringUtils.isEmpty(fnSku)) {
            List<String> countryList = mwsDailyInventoryHistoryMapper.selectCountryByFuSku(fnSku);
            if (countryList.contains(US)) {
                country = US;
            } else if (countryList.contains(CA)) {
                country = CA;
            } else if (countryList.contains(MX)) {
                country = MX;
            } else {
                country = "area";
            }
        }
        return country;
    }


    /**
     * 获取stockSku
     *
     * @param sku
     * @param country
     * @param sellerId
     * @param fbaShipmentId
     * @return 返回的集合中的键后缀数字是stock_sku_status的值，
     */
    public Map<String, String> getStockSku(String sku, String country, String sellerId, String fbaShipmentId) {
        if (!StringUtils.isEmpty(country)) {
            if (country.equals(EU)) {
                country = "o5";
            } else {
                country = country.toLowerCase();
            }
            if (StringUtils.isEmpty(sellerId) || StringUtils.isEmpty(sku) || StringUtils.isEmpty(fbaShipmentId)) {
                log.info("获取stockSku时，sellerId、sku、fbaShipmentId三者有为空情况，已接收库存财务数据生成！" + "sellerId: " + sellerId + "sku: " + sku + "fbaShipmentId: " + fbaShipmentId);
            }
            List<String> stockSkuList = caravanMskuDataMapper.selectStockSkuBySkuAndAmazonSite(sku, country);
            if (null != stockSkuList && !stockSkuList.isEmpty()) {
                if (stockSkuList.size() == 1) {
                    return new HashMap<String, String>(1) {{
                        put("stockSku", stockSkuList.get(0));
                    }};
                } else {
                    String stockSku = caravanMskuDataMapper.selectStockSkuBySellerIdAndCountryAndSku(sellerId, country, sku);
                    if (!StringUtils.isEmpty(stockSku)) {
                        return new HashMap<String, String>(1) {{
                            put("stockSku", stockSku);
                        }};
                    }
                }
                if (stockSkuList.size() > 1) {
                    if (!StringUtils.isEmpty(fbaShipmentId)) {
                        List<String> stockSkuListByFbaShipmentId = caravanStorageLogDataMapper.selectStockSkuByDocumentNumAndStockSkuList(fbaShipmentId, stockSkuList);
                        if (null != stockSkuListByFbaShipmentId && !stockSkuListByFbaShipmentId.isEmpty() && stockSkuListByFbaShipmentId.size() == 1) {
                            return new HashMap<String, String>(1) {{
                                put("stockSku4", stockSkuListByFbaShipmentId.get(0));
                            }};
                        } else {
                            String stockSkuByFReceive = fReceiveMapper.selectStockSkuBySellerIdAndCountryAndSku(sellerId, country, sku);
                            if (StringUtils.isEmpty(stockSkuByFReceive)) {
                                return new HashMap<String, String>(1) {{
                                    put("stockSku3", stockSkuByFReceive);
                                }};
                            } else {
                                return new HashMap<String, String>(1) {{
                                    put("stockSku2", stockSkuByFReceive);
                                }};
                            }
                        }
                    } else {
                        log.info("根据shipmentId获取stockSku时，shipmentId为空，已接收库存财务数据生成！");
                    }
                }
            }
        } else {
            log.info("获取stockSku时，country为空，已接收库存财务数据生成！");
        }
        log.info("获取stockSku时，遇到未出现的情况，已接收库存财务数据生成！");
        return null;
    }

    /**
     * 获取cost_unit,四种方案
     *
     * @param sellerId
     * @param country
     * @param sku
     * @param stockSku
     * @param shipmentId
     * @return 第四种方案返回的map的key值为costUnit2 其余三种方案返回的是costUnit
     */
    public Map<String, Double> getCostUnit(String sellerId, String country, String sku, String stockSku, String shipmentId) throws ParseException {
        String costUnit = "costUnit";
        if (!StringUtils.isEmpty(stockSku) && !StringUtils.isEmpty(shipmentId)) {
            // 第一种方式获取 costUnit
            Map<String,Object> amountAndSkuNumMap = financeCaravanDebitCreditRelationMapper.selectSumAmountAndSumSkuNumByStockSkuAndShipmentIdAndSubjectId(stockSku,shipmentId,"140205");
            if (null  != amountAndSkuNumMap && null != amountAndSkuNumMap.get("amount") && null != amountAndSkuNumMap.get("skuNum")) {
                Double amount = new Double(amountAndSkuNumMap.get("amount").toString());
                Integer quantity = new Integer(amountAndSkuNumMap.get("skuNum").toString());
                if (null != amount && null != quantity && amount != 0 && quantity != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }
            // 根据related_record_no匹配shipmentId获取costUnit  related_record_no = related_record_no
            Map<String,Object> amountAndSkuNumMapBySingleRelatedRecordNo= financeCaravanDebitCreditRelationMapper.selectSumAmountAndSumSkuNumBySkuAndSingleRelatedRecordNoAndSubjectId(stockSku,shipmentId,"140205");
            if (null  != amountAndSkuNumMapBySingleRelatedRecordNo && null != amountAndSkuNumMapBySingleRelatedRecordNo.get("amount") && null != amountAndSkuNumMapBySingleRelatedRecordNo.get("skuNum")) {
                Double amount = new Double(amountAndSkuNumMapBySingleRelatedRecordNo.get("amount").toString());
                Integer quantity = new Integer(amountAndSkuNumMapBySingleRelatedRecordNo.get("skuNum").toString());
                if (null != amount && null != quantity && amount != 0 && quantity != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }
            // 根据related_record_no匹配shipmentId获取costUnit  related_record_no = related_record_no
            Map<String,Object> amountAndSkuNumMapByMoreRelatedRecordNo= financeCaravanDebitCreditRelationMapper.selectSumAmountAndSumSkuNumBySkuAndMoreRelatedRecordNoAndSubjectId(stockSku,shipmentId,"140205");
            if (null  != amountAndSkuNumMapByMoreRelatedRecordNo && null != amountAndSkuNumMapByMoreRelatedRecordNo.get("amount") && null != amountAndSkuNumMapByMoreRelatedRecordNo.get("skuNum")) {
                Double amount = new Double(amountAndSkuNumMapByMoreRelatedRecordNo.get("amount").toString());
                Integer quantity = new Integer(amountAndSkuNumMapByMoreRelatedRecordNo.get("skuNum").toString());
                if (null != amount && null != quantity && amount != 0 && quantity != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }
            // 第二种方式获取
            Double amountByInventory = fInventoryDailyMapper.selectSumAmountByStockSkuAndShipmentIdAndWarehouse(stockSku, shipmentId, "140205");
            Integer quantityByInventory = fInventoryDailyMapper.selectSumQuantityByStockSkuAndShipmentIdAndWarehouse(stockSku, shipmentId, "140205");
            if (null != amountByInventory && null != quantityByInventory && amountByInventory != 0 && quantityByInventory != 0) {
                return new HashMap<String, Double>(1) {{
                    put(costUnit, new BigDecimal(amountByInventory / quantityByInventory).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                }};
            }
        }
        if (!StringUtils.isEmpty(sellerId) && !StringUtils.isEmpty(country) && !StringUtils.isEmpty(sku) && !StringUtils.isEmpty(stockSku)) {
            // 第四种方式获取
            Map<String, Object> amountAndQuantityMap = fInventoryDailyMapper.selectSumAmountAndSumQuantityBySellerIdAndCountryAndSkuAndWarehouse(sellerId, country, sku, "140603");
            if (null  != amountAndQuantityMap && null != amountAndQuantityMap.get("amount") && null != amountAndQuantityMap.get("quantity")) {
                Double amount = new Double(amountAndQuantityMap.get("amount").toString());
                Integer quantity = new Integer(amountAndQuantityMap.get("quantity").toString());
                if (null != amount && null != quantity && amount != 0 && quantity != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit3", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }
            // 第五种方式获取
            Map<String, Object> amountAndQuantityMapByWarehouse = fInventoryDailyMapper.selectSumAmountAndSumQuantityBySellerIdAndCountryAndSkuAndWarehouse(sellerId, country, sku, "140605");
            if (null  != amountAndQuantityMapByWarehouse && null != amountAndQuantityMapByWarehouse.get("amount") && null != amountAndQuantityMapByWarehouse.get("quantity")) {
                Double amount = new Double(amountAndQuantityMapByWarehouse.get("amount").toString());
                Integer quantity = new Integer(amountAndQuantityMapByWarehouse.get("quantity").toString());
                if (null != amount && null != quantity && amount != 0 && quantity != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit4", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }
            String warehouse = "默认仓库";
            String subjectId = "1406";
            Map<String, Object> amountAndSkuNumMap = financeCaravanDebitCreditRelationMapper.selectSumSkuNumAndSumAmountByStockSkuAndWarehouseAndSubjectId(stockSku,warehouse,subjectId);
            if(null != amountAndSkuNumMap && null != amountAndSkuNumMap.get("amount") && null != amountAndSkuNumMap.get("skuNum")){
                Double amount = new Double(amountAndSkuNumMap.get("amount").toString());
                Integer skuNum = new Integer(amountAndSkuNumMap.get("skuNum").toString());
                if (null != amount && null != skuNum && amount != 0 && skuNum != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit5", new BigDecimal((amount / skuNum)+15).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }
            // 第六种方式获取
            Map<String, Object> amountAndQuantityMapByInventory = fInventoryDailyMapper.selectSumAmountAndSumQuantityBySellerIdAndCountryAndSkuAndWarehouse(sellerId, country, sku, null);
            if (null  != amountAndQuantityMapByInventory && null != amountAndQuantityMapByInventory.get("amount") && null != amountAndQuantityMapByInventory.get("quantity")) {
                Double amount = new Double(amountAndQuantityMapByInventory.get("amount").toString());
                Integer quantity = new Integer(amountAndQuantityMapByInventory.get("quantity").toString());
                if (null != amount && null != quantity && amount != 0 && quantity != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit6", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }

        }
        log.info("获取成本单价使用默认值60，已接收库存."+"sellerId:"+sellerId+"country: "+country+"sku:"+sku);
        // 最后默认返回60
        return new HashMap<String, Double>(1) {{
            put("costUnit7", new BigDecimal(60).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
        }};
    }

}
